package com.flycms.modules.user.service.impl;

import com.flycms.common.pager.Pager;
import com.flycms.common.utils.DateUtils;
import com.flycms.common.utils.RandomNameUtils;
import com.flycms.common.utils.bcrypt.BCrypt;
import com.flycms.common.utils.mark.SnowFlakeUtils;
import com.flycms.common.utils.result.LayResult;
import com.flycms.common.utils.result.Result;
import com.flycms.modules.notify.service.AliyunService;
import com.flycms.modules.shiro.ShiroUtils;
import com.flycms.modules.shiro.UserToken;
import com.flycms.modules.system.service.ConfigureService;
import com.flycms.modules.user.dao.UserActivationDao;
import com.flycms.modules.user.dao.UserDao;
import com.flycms.modules.user.entity.RegisterUserVO;
import com.flycms.modules.user.entity.User;
import com.flycms.modules.user.entity.UserActivation;
import com.flycms.modules.user.service.UserRoleService;
import com.flycms.modules.user.service.UserService;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;

/**
 * Open source house, All rights reserved
 * 版权：28844.com<br/>
 * 开发公司：28844.com<br/>
 *
 * @author sun-kaifei
 * @version 1.0 <br/>
 * @email 79678111@qq.com
 * @Date: 11:19 2019/8/18
 */
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;
    @Autowired
    private UserRoleService userRoleService;
    @Autowired
    private ConfigureService systemService;
    @Autowired
    private UserActivationDao userActivationDao;
    @Autowired
    private AliyunService aliyunService;

    // ///////////////////////////////
    // /////       增加       ////////
    // ///////////////////////////////

    /**
     * 用户手机注册账号申请获取验证码
     *
     * @param phoneNumber
     *        手机号码
     * @return
     * @throws Exception
     */
    public Object regMobileCode(String phoneNumber)throws Exception {
        if(this.checkUserByMobile(phoneNumber,null)) {
            return Result.failure("该手机号码以注册或被占用！");
        }
        int count=userActivationDao.checkUserActivationCount(phoneNumber,DateUtils.getDay());
        if(count<=5) {
            aliyunService.sendSms(phoneNumber,"home_sms_user_reg");
        }else {
            return Result.failure("您今日已超出申请次数！");
        }
        return Result.success("验证码已发送，请注意查收！");
    }

    /**
     * 添加用户信息
     *
     * @param reg
     *         用户提交注册信息
     * @return
     */
    @Transactional
    public Result addUser(RegisterUserVO reg) {
        if(this.checkUserByMobile(reg.getUserName(),null)){
            return Result.failure("该手机号已被占用");
        }

        if (this.checkUserActivationCode(reg.getUserName(),1, reg.getVercode())) {
            //验证通过后修改本条记录为已验证
            userActivationDao.updateUserActivationByStatus(reg.getUserName(),reg.getVercode());
        }else {
            return Result.failure("手机验证码错误或者已过期");
        }
        User user = new User();
        user.setId(SnowFlakeUtils.nextId());
        user.setUserMobile(reg.getUserName());
        String pwHash = BCrypt.hashpw(reg.getPassword(), BCrypt.gensalt());
        user.setPassword(pwHash);
        //随机给用户一个昵称
        user.setNickname(RandomNameUtils.randomName(true,3));
        user.setCreateTime(LocalDateTime.now());
        int total = userDao.save(user);
        if(total > 0){
            //用户注册时默认权限组
            userRoleService.addUserRoleMerge(user.getId(),Long.parseLong(systemService.findByKeyCode("role_user_id")));
            //查询登录信息
            Subject subject = ShiroUtils.getSubject();
            UsernamePasswordToken token = new UserToken(user.getUserMobile(), reg.getPassword());
            subject.login(token);
            return Result.success("注册成功","/member/index.do");
        }else{
            return Result.failure("注册失败");
        }

    }
    // ///////////////////////////////
    // /////        刪除      ////////
    // ///////////////////////////////
    /**
     * 按id删除用户主表信息
     *
     * @param id
     * @return
     */
    public int deleteById(Long id){
        return userDao.deleteById(id);
    }
    // ///////////////////////////////
    // /////        修改      ////////
    // ///////////////////////////////
    /**
     * 用户修改密码
     *
     * @param oldPassword
     *        旧密码
     * @param password
     *        新密码
     * @throws Exception
     */
    @Transactional
    public Result updatePassword(String oldPassword, String password) {
        Long userId = ShiroUtils.getLoginUser().getId();
        User user = userDao.findById(userId);
        if (user == null) {
            return Result.failure("未登录或未获取到用户信息！");
        }
        if (BCrypt.checkpw(oldPassword, user.getPassword())) {
            String pwHash = BCrypt.hashpw(password, BCrypt.gensalt());
            userDao.updatePassword(pwHash,userId);
        } else {
            return  Result.failure("原始密码错误");
        }
        return  Result.success("密码已修改","/member/user/password.do");
    }


    // ///////////////////////////////
    // /////        查詢      ////////
    // ///////////////////////////////

    /**
     * 排除当前用户id后查询用户名是否存在,如果userId设置为null则查全部的用户名
     *
     * @param userName
     *         用户登录手机号码
     * @param id
     *         需要排除的user_id,可设置为null
     * @return
     */
    public boolean checkUserByUserName(String userName,Long id) {
        int totalCount = userDao.checkUserByUserName(userName,id);
        return totalCount > 0 ? true : false;
    }

    /**
     * 排除当前用户id后查询手机号码是否存在,如果userId设置为null则查全部的手机号码
     *
     * @param userMobile
     *         用户登录手机号码
     * @param id
     *         需要排除的user_id,可设置为null
     * @return
     */
    public boolean checkUserByMobile(String userMobile,Long id) {
        int totalCount = userDao.checkUserByMobile(userMobile,id);
        return totalCount > 0 ? true : false;
    }

    /**
     * 查询验证码在当前时间5分钟内获取并且是否过时或不存在
     *
     * @param userName
     *         查询的用户名
     * @param codeType
     *         查询的验证码类型，1手机注册验证码,2安全手机设置验证码,3密码重置验证码
     * @param code
     *         验证码
     * @return
     */
    public boolean checkUserActivationCode(String userName,Integer codeType,String code){
        UserActivation activation = userActivationDao.findByUserActivationCode(userName,codeType);
        if(activation!=null){
            if(activation.getCode().equals(code)){
                return true;
            }
        }
        return false;
    }

    /**
     * 按用户名id查询用户注册信息
     *
     * @param id
     * @return
     */
    public User findById(Long id) {
        return userDao.findById(id);
    }

    /**
     * 通过username查询用户信息
     *
     * @param userName
     * @return User
     */
    public User findByUsername(String userName) {
        return userDao.findByUsername(userName);
    }


    /**
     * 翻页列表
     *
     * @param userName
     *         根据分类名查询
     * @param page
     * @param limit
     * @param sort
     * @param order
     * @return
     */
    public Object selectUserListPager(String userName, Integer page, Integer limit, String sort, String order) {
        StringBuffer whereStr = new StringBuffer(" 1 = 1");
        if (!StringUtils.isEmpty(userName)) {
            whereStr.append(" and user_name like concat('%',#{entity.userName},'%')");
        }
        whereStr.append(" and deleted = 0");

        Pager<User> pager = new Pager(page, limit);
        //排序设置
        if (!StringUtils.isEmpty(sort)) {
            Boolean rank = "desc".equals(order) ? true : false;
            pager.addOrderProperty(sort, rank,true);
        }
        //使用limit进行查询翻页
        pager.addLimitProperty(true);
        //查询条件
        User user = new User();
        user.setUserName(userName);
        pager.setEntity(user);
        pager.setWhereStr(whereStr.toString());
        return LayResult.success(0, "true", userDao.queryTotal(pager), userDao.queryList(pager));
    }
}
